package com.zhglxt.oa.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhglxt.activiti.service.impl.ActTaskService;
import com.zhglxt.activiti.util.ActUtils;
import com.zhglxt.common.core.entity.sys.SysRole;
import com.zhglxt.common.core.entity.sys.SysUser;
import com.zhglxt.common.core.text.Convert;
import com.zhglxt.common.utils.ShiroUtils;
import com.zhglxt.common.utils.uuid.UUID;
import com.zhglxt.framework.redisCache.IGlobalCache;
import com.zhglxt.oa.entity.BusinessTrip;
import com.zhglxt.oa.entity.Notify;
import com.zhglxt.oa.mapper.BusinessTripMapper;
import com.zhglxt.oa.service.IBusinessTripService;
import com.zhglxt.oa.service.INotifyService;
import com.zhglxt.system.service.ISysRoleService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @Description 请假业务实现层
 * @Author liuwy
 * @Date 2019/9/27
 **/
@Service
public class BusinessTripServiceImpl implements IBusinessTripService {

    @Autowired
    private BusinessTripMapper businessTripMapper;

    @Autowired
    private ActTaskService actTaskService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private ISysRoleService roleService;

    /**
     * redis缓存
     */
    @Autowired
    private IGlobalCache iGlobalCache;

    @Autowired
    private INotifyService notifyService;

    private final Logger logger = LoggerFactory.getLogger(BusinessTripServiceImpl.class);

    @Override
    public List<BusinessTrip> getBusinessTripList(Map<String, Object> paramMap) {
        // 获取当前用户
        SysUser user = ShiroUtils.getSysUser();
        // 获取当前登录人所有角色列表
        Set<String> roleKeys = new HashSet<String>();
        roleKeys = roleService.selectRoleKeys(user.getUserId());
        List<SysRole> allRoles = roleService.selectRoleAll();
//        logger.info("所有的角色是：{}", allRoles);
//        logger.info("当前登录用户的角色是：{}", roleKeys);
        // 普通用户查自己的请假记录


        // 匹配用户的角色
        for (String userRoleKey : roleKeys) {
            // 所有的角色
            for (SysRole role : allRoles) {
                if (userRoleKey.equalsIgnoreCase(role.getRoleKey())) {
                    //管理权限小的数据查看权限
                    //普通用户查自己的请假记录
                    if (roleKeys.contains("common")) {//普通用户
                        paramMap.put("userId", user.getUserId());
                    }
                    // 部门经理查询所在部门的请假记录
                    if (userRoleKey.contains("dept")) {
                        paramMap.put("userId", null);
                        paramMap.put("deptId", user.getDeptId());
                    }
                    // hr及其他管理层查询所有的请假记录
                }
            }

        }

        // 查看下传入的参数--logger
//        paramMap.entrySet().forEach(entry -> {
//            logger.info("参数是：key:{},value:{}", entry.getKey(), entry.getValue());
//        });


        List<BusinessTrip> leaveList = businessTripMapper.getBusinessTripList(paramMap);

        List<BusinessTrip> leaves = new ArrayList<>();
        //查询请假单当前所在环节
        for (BusinessTrip businessTrip : leaveList) {

            String procInsId = businessTrip.getProcInsId();
            logger.info("procInsId:{}", procInsId);
            Task task = taskService.createTaskQuery().processInstanceId(procInsId).singleResult();

            logger.info("当前的任务的环节task是：{}", task);

            // procIns.get
            if (task != null) {
//                Act act=new Act();
//                act.setTask(task);
//                act.setTaskName(task.getName());
                businessTrip.setCurrentTaskName(task.getName());
            }
            if (businessTrip.getProcInsId() != null && task == null) {
                businessTrip.setCurrentTaskName("任务已结束");
            }
            leaves.add(businessTrip);
            logger.info("leave是：{}", businessTrip);
        }
        return leaves;
    }

    /**
     * 保存请假信息
     *
     * @param paramMap
     * @return
     */
    @Transactional(readOnly = false)
    public String save(Map<String, Object> paramMap) {
        String resoult = "0";
        //获取当前用户
        SysUser user = ShiroUtils.getSysUser();
        //初始自定义业务表id
        if (!paramMap.containsKey("id")) {
            //新增保存
            // 自定义生成流程业务表之请假表的id
            paramMap.put("id", UUID.fastUUID());

            paramMap.put("createBy", user.getUserId());
            // todo
            paramMap.put("createDate", new Date());
            // todo
            paramMap.put("updateBy", user.getUserId());
            paramMap.put("updateDate", new Date());
            // todo
            paramMap.put("delFlag", 0);
            //插入数据库

//            paramMap.entrySet().forEach(entry -> {
//                logger.info("BusinessTripServiceImpl::save方法得到的参数：:key:{},value:{}", entry.getKey(), entry.getValue());
//            });

            businessTripMapper.insert(paramMap);

            // 启动流程,请假流程的启动
            String procDefKey = ActUtils.PD_BUSINESSTRIP[0];
            String businessTable = ActUtils.PD_BUSINESSTRIP[1];
            String businessId = paramMap.get("id").toString();
            String title = paramMap.get("content").toString();
            HashMap<String, Object> vars = Maps.newHashMap();
            // 启动流程，手动动态指定审批人
//            vars.put("userId",25);
            // 特定需求测试,动态设置下一节点审批人，后续逻辑处理审批人分配，applyUserId是启动器变量，可覆盖
            // empUserId 员工的ID，需要后面逻辑获取其上级领导ID
            String auditUserId = paramMap.get("auditUserId").toString();
            String auditUserName = paramMap.get("auditUserName").toString();
            vars.put("auditUserId",auditUserId);
            SysUser auditUser=new SysUser();
            auditUser.setUserId(auditUserId);
            auditUser.setUserName(auditUserName);
//            logger.info("流程的审批人是:{}",auditUserId);

            /**
             * 将审批人id保存到session或者redis缓存中
             * redis key:auditUserRecord_applyUserId_用户ID
             */
//            String auditUserRecord="auditUserRecord"+user.getUserId();
            // 保存到redis缓存中
           iGlobalCache.hset("auditUserRecord","auditUserForDept",auditUser);
           //redis中保存流程发起人用户ID
            iGlobalCache.hset("auditUserRecord","applyUserId",user.getUserId());
            actTaskService.startProcess(procDefKey, businessTable, businessId, title,vars);

            // 创建通知，提醒代办人查看
            Notify notify = new Notify();
            notify.setNotifyTitle("审批待办查收通知");
            notify.setNotifyType("4");
            notify.setNotifyContent("您有一个新的待办任务，请查收。");
            ArrayList<String> userIds = Lists.newArrayList();
            userIds.add(auditUserId);
            notify.setUserIds(userIds);
            // 设置发布状态
            notify.setStatus("1");
            notifyService.insertNotify(notify);
            logger.info("发送了一个通知，等待任务接收人查看");

            resoult = "1";
        } else {
            //请假驳回后更新请假表单操作
            paramMap.put("updateBy", user.getUserId());
            paramMap.put("updateDate", new Date());
            // 更新请假操作时的参数
            logger.info("更新出差操作时的参数");
            paramMap.entrySet().forEach(entry -> {
                logger.info("BusinessTripServiceIMpl::paramMap:key:{},value:{}", entry.getKey(), entry.getValue());
            });
            // 修改请假信息
            businessTripMapper.update(paramMap);

            String actFlag = paramMap.get("act.flag").toString();
            logger.info("actFlag:{}",actFlag);
            // 完成流程任务
            Map<String, Object> vars = Maps.newHashMap();

            if ("yes".equalsIgnoreCase(actFlag)){
                // 流程任务审批内容
               paramMap.put("act.comment","[重申]");
                // 流程任务设置变量参数，与前端的参数作比较
               vars.put("flag","1");

                String auditUserId = paramMap.get("auditUserId").toString();
                vars.put("auditUserId",auditUserId);
                logger.info("请假驳回后更新请假表单后续流程的审批人ID是:{}",auditUserId);

                String auditUserName = paramMap.get("auditUserName").toString();
                SysUser auditUser=new SysUser();
                auditUser.setUserId(auditUserId);
                auditUser.setUserName(auditUserName);

                // todo
                /**
                 * 将审批人id保存到session或者redis缓存中
                 *
                 */
                // 保存到redis缓存中
                iGlobalCache.hset("auditUserRecord","auditUserForDept",auditUser);

                // 创建通知，提醒代办人查看
                Notify notify = new Notify();
                notify.setNotifyContent("您有一个新的待办任务，请查收。");
                ArrayList<String> userIds = Lists.newArrayList();
                userIds.add(auditUserId);
                notify.setUserIds(userIds);
                notify.setNotifyTitle("部门经理审批待办查收通知");
                notify.setNotifyType("4");
                // 设置发布状态
                notify.setStatus("1");
                notifyService.insertNotify(notify);
                logger.info("发送了一个通知，等待任务接收人查看");

            }else{
                // 流程任务审批内容
                paramMap.put("act.comment","[销毁]");
                // 流程任务设置变量参数，与前端的参数作比较
                vars.put("flag","0");
                // 删除缓存
                iGlobalCache.del("auditUserRecord");
            }

            // 完成当前任务

            actTaskService.complete(paramMap.get("act.taskId").toString(), paramMap.get("act.procInsId").toString(), paramMap.get("act.comment").toString(), paramMap.get("content").toString(), vars);




            resoult = "2";
        }
//        logger.info("保存请假信息返回结果：{}", resoult);
        return resoult;
    }

    /**
     * 根据id 删除请假信息
     */
    @Override
    @Transactional
    public int updateBusinessTripInFoByIds(Map paramsToMap) {
        List<String> idList = Arrays.asList(paramsToMap.get("ids").toString().split(","));
        paramsToMap.put("ids", idList);
        return businessTripMapper.updateBusinessTripInFoByIds(paramsToMap);
    }

    /**
     * 根据id 删除请假信息
     */
    @Override
    @Transactional
    public int updateBusinessTripInFoToList(Map paramsToMap) {
        String[] ids = paramsToMap.get("ids").toString().split(",");
        List<String> idList = Arrays.asList(ids);
        return businessTripMapper.updateBusinessTripInFoToList(idList);
    }

    /**
     * 根据id 删除请假信息
     */
    @Override
    @Transactional
    public int updateBusinessTripInFoToArray(Map paramsToMap) {
        String[] idArray = Convert.toStrArray(paramsToMap.get("ids").toString());
        return businessTripMapper.updateBusinessTripInFoToArray(idArray);
    }

    /**
     * 根据id查询请假信息
     *
     * @return
     */
    public BusinessTrip getBusinessTripById(BusinessTrip businessTrip) {
        return businessTripMapper.getBusinessTripById(businessTrip);
    }

    /**
     * 审核审批保存
     *
     * @param businessTrip
     * @return
     */
    @Transactional(readOnly = false)
    public int auditSave(BusinessTrip businessTrip) {
        int i = 1;
        SysUser sysUser = ShiroUtils.getSysUser();
        // 设置意见
        businessTrip.getAct().setComment(("yes".equals(businessTrip.getAct().getFlag()) ? "[同意] " : "[驳回] ") + businessTrip.getAct().getComment());

        businessTrip.preUpdate();

        // 对不同环节的业务逻辑进行操作
        String taskDefKey = businessTrip.getAct().getTaskDefKey();

        // 提交流程变量
        Map<String, Object> vars = Maps.newHashMap();

        logger.info("auditSave方法leave参数：{}", businessTrip);
        logger.info("auditSave方法leave.taskDefKey参数：{}", taskDefKey);

        Notify notify =null;
        /**
         * 处理业务信息
         */
        //更新部门经理审批意见
        if ("deptAudit".equals(taskDefKey)) {
            businessTrip.setDeptText(businessTrip.getAct().getComment());
            businessTripMapper.updateDeptText(businessTrip);
            String auditUserId = businessTrip.getAuditUserId();
            String auditUserName = businessTrip.getAuditUserName();
            logger.info("流程的审批人是：{}",auditUserId);
            SysUser auditUser=new SysUser();
            auditUser.setUserName(auditUserName);
            auditUser.setUserId(auditUserId);
            // 将审批人id保存到session中

            vars.put("auditUserId",auditUserId);
            /**
             * 将审批人id保存到session或者redis缓存中
             *
             */
            iGlobalCache.hset("auditUserRecord","auditUserForCEO",auditUser);

            // 创建通知，提醒代办人查看
            notify = new Notify();
            notify.setNotifyContent("您有一个新的待办任务，请查收。");
            ArrayList<String> userIds = Lists.newArrayList();
            userIds.add(auditUserId);
            notify.setUserIds(userIds);
            notify.setNotifyTitle("总经理审批待办查收通知");
            notify.setNotifyType("4");
            // 设置发布状态
            notify.setStatus("1");

        }

        //更新总经理审批意见
        else if ("ceoAudit".equals(taskDefKey)) {
            businessTrip.setZjlText(businessTrip.getAct().getComment());
            businessTripMapper.updateZjlText(businessTrip);
            String hget = (String)iGlobalCache.hget("auditUserRecord", "applyUserId");
            // 创建通知，提醒代办人查看
          notify = new Notify();
            notify.setNotifyContent("您有一个新的待办任务，请查收。");
            String applyUserId =(String) iGlobalCache.hget("auditUserRecord", "applyUserId");
            ArrayList<String> userIds = Lists.newArrayList();
            userIds.add(applyUserId);
            notify.setUserIds(userIds);
            notify.setNotifyTitle("销毁待办查收通知");
            notify.setNotifyType("4");
            // 设置发布状态
            notify.setStatus("1");
            notifyService.insertNotify(notify);
            logger.info("发送了一个通知，等待任务接收人查看");

        } else if ("tripAudit".equals(taskDefKey)) {
            businessTrip.getAct().setComment("[同意]");
            // 删除审批人缓存
            iGlobalCache.del("auditUserRecord");
        }
        // 未知环节，直接返回
        else {
            return i;
        }

        String actFlag = businessTrip.getAct().getFlag();
        if ("yes".equalsIgnoreCase(actFlag)){
            vars.put("flag","1");
            notifyService.insertNotify(notify);
            logger.info("发送了一个通知，等待任务接收人查看");
        }else{
            vars.put("flag","0");
            String applyUserId = (String)iGlobalCache.hget("auditUserRecord", "applyUserId");

            ArrayList<String> userIds = Lists.newArrayList();
            userIds.add(applyUserId);
            notify.setUserIds(userIds);
            notify.setNotifyTitle("审批被驳回通知");
            notifyService.insertNotify(notify);
            logger.info("发送了一个通知，等待任务接收人查看");
        }
        /**
         * 完成当前任务
         */

        actTaskService.complete(businessTrip.getAct().getTaskId(), businessTrip.getAct().getProcInsId(), businessTrip.getAct().getComment(), vars);
        i = 0;
        logger.info("完成当前任务：返回结果：{}", i);
        return i;
    }

}
